﻿using Sasa.QualityTools.CodeAnalysis.Common;
using Sasa.QualityTools.CodeAnalysis.Core.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels
{
    public class FxCopDictionaryViewModel : ViewModelBase
    {
        public event EventHandler Saving;

        public event EventHandler Saved;

        public event EventHandler CloseRequired;


        private FxCopDictionary custom;


        public ICollection<DictionaryTermViewModel> Recognized { get; private set; }

        public ICollection<DictionaryTermViewModel> Unrecognized { get; private set; }

        public ICollection<DictionaryTermViewModel> Deprecated { get; private set; }

        public ICollection<DictionaryTermViewModel> Compound { get; private set; }

        public ICollection<DictionaryTermViewModel> DiscreteExceptions { get; private set; }

        public ICollection<DictionaryTermViewModel> CasingExceptions { get; private set; }

        public RelayCommand SaveAndCloseCommand { get; private set; }

        public RelayCommand SaveCommand { get; private set; }

        public RelayCommand CloseCommand { get; private set; }


        public FxCopDictionaryViewModel(FxCopDictionary buildin, FxCopDictionary custom)
        {
            this.custom = custom;

            Recognized = new ObservableCollection<DictionaryTermViewModel>();
            Unrecognized = new ObservableCollection<DictionaryTermViewModel>();
            Deprecated = new ObservableCollection<DictionaryTermViewModel>();
            Compound = new ObservableCollection<DictionaryTermViewModel>();
            DiscreteExceptions = new ObservableCollection<DictionaryTermViewModel>();
            CasingExceptions = new ObservableCollection<DictionaryTermViewModel>();

            SaveAndCloseCommand = new RelayCommand(o => { Save(); Close(); });
            SaveCommand = new RelayCommand(o => Save());
            CloseCommand = new RelayCommand(o => Close());

            if (buildin.Words != null)
            {
                buildin.Words.Recognized.Select(o => new DictionaryTermViewModel { Value = o, IsReadOnly = true }).ForEach(o => Recognized.Add(o));
                buildin.Words.Unrecognized.Select(o => new DictionaryTermViewModel { Value = o, IsReadOnly = true }).ForEach(o => Unrecognized.Add(o));
                buildin.Words.Deprecated.Select(o => new DictionaryTermViewModel { Value = o.Value, Alternate = o.Alternate, IsReadOnly = true }).ForEach(o => Deprecated.Add(o));
                buildin.Words.Compound.Select(o => new DictionaryTermViewModel { Value = o.Value, Alternate = o.Alternate, IsReadOnly = true }).ForEach(o => Compound.Add(o));
                buildin.Words.DiscreteExceptions.Select(o => new DictionaryTermViewModel { Value = o, IsReadOnly = true }).ForEach(o => DiscreteExceptions.Add(o));
            }

            if (buildin.Acronyms != null)
            {
                buildin.Acronyms.CasingExceptions.Select(o => new DictionaryTermViewModel { Value = o, IsReadOnly = true }).ToList().ForEach(o => CasingExceptions.Add(o));
            }

            if (custom.Words != null)
            {
                custom.Words.Recognized.Select(o => new DictionaryTermViewModel { Value = o }).ForEach(o => Recognized.Add(o));
                custom.Words.Unrecognized.Select(o => new DictionaryTermViewModel { Value = o }).ForEach(o => Unrecognized.Add(o));
                custom.Words.Deprecated.Select(o => new DictionaryTermViewModel { Value = o.Value, Alternate = o.Alternate }).ForEach(o => Deprecated.Add(o));
                custom.Words.Compound.Select(o => new DictionaryTermViewModel { Value = o.Value, Alternate = o.Alternate }).ForEach(o => Compound.Add(o));
                custom.Words.DiscreteExceptions.Select(o => new DictionaryTermViewModel { Value = o }).ForEach(o => DiscreteExceptions.Add(o));
            }

            if (custom.Acronyms != null)
            {
                custom.Acronyms.CasingExceptions.Select(o => new DictionaryTermViewModel { Value = o }).ToList().ForEach(o => CasingExceptions.Add(o));
            }
        }

        private void Save()
        {
            if (Saving != null)
            {
                Saving(this, EventArgs.Empty);
            }

            custom.Words = new Words();
            custom.Acronyms = new Acronyms();

            Recognized.Where(o=> !o.IsReadOnly).Select(o => o.Value).ForEach(o => custom.Words.Recognized.Add(o));
            Unrecognized.Where(o=> !o.IsReadOnly).Select(o => o.Value).ForEach(o => custom.Words.Unrecognized.Add(o));
            Deprecated.Where(o=> !o.IsReadOnly).Select(o => new DeprecatedTerm { Value = o.Value, Alternate = o.Alternate }).ForEach(o => custom.Words.Deprecated.Add(o));
            Compound.Where(o=> !o.IsReadOnly).Select(o => new CompoundTerm { Value = o.Value, Alternate = o.Alternate }).ForEach(o => custom.Words.Compound.Add(o));
            DiscreteExceptions.Where(o=> !o.IsReadOnly).Select(o => o.Value).ForEach(o => custom.Words.DiscreteExceptions.Add(o));
            CasingExceptions.Where(o=> !o.IsReadOnly).Select(o => o.Value).ForEach(o => custom.Acronyms.CasingExceptions.Add(o));

            custom.Save();

            if (Saved != null)
            {
                Saved(this, EventArgs.Empty);
            }
        }

        private void Close()
        {
            if (CloseRequired != null)
            {
                CloseRequired(this, EventArgs.Empty);
            }
        }


        public class DictionaryTermViewModel : ViewModelBase
        {
            private string value;

            private string alternate;

            private bool isReadOnly;


            public string Value
            {
                get
                {
                    return value;
                }
                set
                {
                    this.value = value;
                    OnPropertyChanged("Value");
                }
            }

            public string Alternate
            {
                get
                {
                    return alternate;
                }
                set
                {
                    alternate = value;
                    OnPropertyChanged("Alternate");
                }
            }

            public bool IsReadOnly
            {
                get
                {
                    return isReadOnly;
                }
                set
                {
                    isReadOnly = value;
                    OnPropertyChanged("IsReadOnly");
                }
            }
        }
    }
}
